package com.zt.event.service.status.listener;

import com.zt.event.service.status.event.CustomsApplicationFailedEvent;
import com.zt.event.service.status.event.CustomsApplicationReadyEvent;
import com.zt.event.service.status.event.CustomsApplicationStartedEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.boot.context.event.EventPublishingRunListener;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.core.Ordered;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.ErrorHandler;

import java.io.InputStreamReader;
import java.util.Properties;

/**
 * @author system
 */
@Slf4j
public class CommonEventPublishingRunListener implements SpringApplicationRunListener, Ordered {

    private final static String GIT_BUILD_PROPERTIES = "git.build.properties";
    public final static String GIT_BRANCH_KEY = "git.branch";
    public static Object GIT_BRANCH_VALUE = "待定";
    public final static Object GIT_BUILD_TIME_KEY = "git.build.time";
    public static Object GIT_BUILD_TIME_VALUE = "待定";
    public final static Object GIT_COMMIT_TIME_KEY = "git.commit.time";
    public static Object GIT_COMMIT_TIME_VALUE = "待定";
    public final static Object GIT_COMMIT_USER_EMAIL_KEY = "git.commit.user.email";
    public static Object GIT_COMMIT_USER_EMAIL_VALUE = "待定";
    public final static Object GIT_COMMIT_USER_NAME_KEY = "git.commit.user.name";
    public static Object GIT_COMMIT_USER_NAME_VALUE = "待定";

    static {
        try {
            Resource resource = new ClassPathResource(GIT_BUILD_PROPERTIES);
            Properties properties = new Properties();
            properties.load(new InputStreamReader(resource.getInputStream()));
            GIT_BRANCH_VALUE = properties.get(GIT_BRANCH_KEY);
            GIT_BUILD_TIME_VALUE = properties.get(GIT_BUILD_TIME_KEY);
            GIT_COMMIT_TIME_VALUE = properties.get(GIT_COMMIT_TIME_KEY);
            GIT_COMMIT_USER_EMAIL_VALUE = properties.get(GIT_COMMIT_USER_EMAIL_KEY);
            GIT_COMMIT_USER_NAME_VALUE = properties.get(GIT_COMMIT_USER_NAME_KEY);
        } catch (Exception e) {
            log.warn("{},{}", e.getMessage(), "没有git.properties文件");
        }
    }

    private final SpringApplication application;

    private final String[] args;

    private final SimpleApplicationEventMulticaster initialMulticaster;

    public CommonEventPublishingRunListener(SpringApplication application, String[] args) {
        this.application = application;
        this.args = args;
        this.initialMulticaster = new SimpleApplicationEventMulticaster();
        for (ApplicationListener<?> listener : application.getListeners()) {
            this.initialMulticaster.addApplicationListener(listener);
        }
    }

    @Override
    public int getOrder() {
        return 0;
    }

    private long startTime;

    private long endTime;


    /**
     * 应用启动完成
     *
     * @param context the application context.
     */
    @Override
    public void started(ConfigurableApplicationContext context) {
        endTime = System.currentTimeMillis();
        context.publishEvent(new CustomsApplicationStartedEvent(this.application, this.args, context, endTime - startTime));
    }

    /**
     * 应用已就绪
     *
     * @param context the application context.
     */
    @Override
    public void running(ConfigurableApplicationContext context) {
        endTime = System.currentTimeMillis();
        context.publishEvent(new CustomsApplicationReadyEvent(this.application, this.args, context, endTime - startTime));
    }

    /**
     * 应用启动失败
     *
     * @param context   the application context or {@code null} if a failure occurred before
     *                  the context was created
     * @param exception the failure
     */
    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        endTime = System.currentTimeMillis();
        CustomsApplicationFailedEvent event = new CustomsApplicationFailedEvent(this.application, this.args, context, exception, endTime - startTime);
        context.publishEvent(event);
    }

    private static class LoggingErrorHandler implements ErrorHandler {

        private static final Log logger = LogFactory.getLog(EventPublishingRunListener.class);

        @Override
        public void handleError(Throwable throwable) {
            logger.warn("Error calling ApplicationEventListener", throwable);
        }

    }

}
